package com.bto.solar.work.lease;

import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.http.Header;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.JSONWriter;
import com.bto.solar.work.common.BizException;
import com.bto.solar.work.common.RedisService;
import com.bto.solar.work.constant.BizLeaseImage;
import com.bto.solar.work.constant.BizStageEnum;
import com.bto.solar.work.constant.BizTaskEnum;
import com.bto.solar.work.constant.BizTaskStateEnum;
import com.bto.solar.work.constant.Constants;
import com.bto.solar.work.dao.IConstructService;
import com.bto.solar.work.dao.ICustomerService;
import com.bto.solar.work.dao.IDesignService;
import com.bto.solar.work.dao.IDeviceService;
import com.bto.solar.work.dao.IGridConnectionService;
import com.bto.solar.work.dao.IInsuranceService;
import com.bto.solar.work.dao.ILeasePrjProjectProductService;
import com.bto.solar.work.dao.ILeasePrjProjectService;
import com.bto.solar.work.dao.ILeaseReviewService;
import com.bto.solar.work.dao.IOrderBaseService;
import com.bto.solar.work.dao.IReconnoitreService;
import com.bto.solar.work.dao.IRecordService;
import com.bto.solar.work.dto.lease.FileContractPushBody;
import com.bto.solar.work.dto.lease.InsuranceRenewalBody;
import com.bto.solar.work.dto.lease.LeaseApprovalNotifyReq;
import com.bto.solar.work.dto.lease.LeaseApprovaledNotifyResp;
import com.bto.solar.work.dto.lease.LeaseHead;
import com.bto.solar.work.dto.lease.LeaseTokenRes;
import com.bto.solar.work.dto.lease.OperatingBody;
import com.bto.solar.work.dto.lease.OperatingRes;
import com.bto.solar.work.dto.lease.OperatingSignBody;
import com.bto.solar.work.dto.lease.PowerSellOlFIleBody;
import com.bto.solar.work.dto.lease.TenantPreAuditBody;
import com.bto.solar.work.entity.Construct;
import com.bto.solar.work.entity.Customer;
import com.bto.solar.work.entity.Design;
import com.bto.solar.work.entity.Device;
import com.bto.solar.work.entity.GridConnection;
import com.bto.solar.work.entity.Insurance;
import com.bto.solar.work.entity.LeasePrjProject;
import com.bto.solar.work.entity.LeasePrjProjectProduct;
import com.bto.solar.work.entity.LeaseReview;
import com.bto.solar.work.entity.OrderBase;
import com.bto.solar.work.entity.OrderState;
import com.bto.solar.work.entity.Reconnoitre;
import com.bto.solar.work.entity.Record;
import com.bto.solar.work.service.BtoDesignService;
import com.bto.solar.work.service.BtoOrderStateService;
import com.bto.solar.work.utils.DateUtils;
import com.bto.solar.work.utils.LogUtils;
import com.bto.solar.work.utils.NullUtils;
import com.bto.solar.work.utils.StringUtils;
import com.bto.solar.work.vo.ImageVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Lazy;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import java.io.IOException;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author 王小波
 * @description: 越秀相关的服务
 * @date 2023/7/20 17:26
 */


@RefreshScope
@Slf4j
@Service
public class LeaseService {
    @Value("${lease.url}")
    private String leaseUrl;
    @Value("${lease.ssl-key}")
    private String sslKey;
    @Value("${lease.token-username}")
    private String tokenUsername;
    @Value("${lease.token-pwd}")
    private String tokenPassword;
    @Value("${lease.system-id}")
    private String systemId;

    @Autowired
    private RedisService redisService;
    @Autowired
    private ICustomerService customerService;
    @Autowired
    private IReconnoitreService reconnoitreService;
    @Autowired
    private IDeviceService deviceService;
    @Autowired
    private IInsuranceService insuranceService;
    @Autowired
    private IGridConnectionService gridConnectionService;
    @Autowired
    private IConstructService constructService;
    @Autowired
    private IDesignService designService;
    @Autowired
    private BtoDesignService btoDesignService;
    @Autowired
    private ILeasePrjProjectService leasePrjProjectService;
    @Autowired
    private ILeasePrjProjectProductService leasePrjProjectProductService;
    @Autowired
    private IOrderBaseService orderService;
    @Autowired
    @Lazy
    private LeaseStateHandler leaseStateHandler;
    @Autowired
    private ILeaseReviewService leaseReviewService;
    @Autowired
    private BtoOrderStateService btoOrderStateService;
    @Autowired
    private IRecordService recordService;


    private ConcurrentHashMap<Map<Integer , Boolean> , HttpRequest> httpRequestMap = null;


    /**
     * token当前失效时间为30分钟
     */
    public LeaseTokenRes getLeaseAccessToken() {
        LeaseTokenRes tokenInfo = redisService.<LeaseTokenRes>getCacheObject(Constants.LEASE_TOKEN);
        if (NullUtils.isNotNull(tokenInfo)) {
            return tokenInfo;
        }

        String authTokenPath = "/oauth/token";
        Map<String, Object> params = new HashMap<>();
        params.put("client_id", "Finance");
        params.put("client_secret", "53e18ab1-67cc-475f-b54b-32c00f8b9bd6");
        params.put("grant_type", "password");
        params.put("username", tokenUsername);
        params.put("password", tokenPassword);
        String response = sendHttpsRequestLease(authTokenPath, params, null, null);
        LeaseTokenRes leaseTokenRes = JSON.parseObject(response, LeaseTokenRes.class);
        assert leaseTokenRes != null;
        String leaseToken = leaseTokenRes.getAccessToken();
        log.info("请求越秀token 成功 {}", leaseToken);

        redisService.setCacheObject(Constants.LEASE_TOKEN, leaseTokenRes, 30L, TimeUnit.MINUTES);

        return leaseTokenRes;

    }

    /**
     * 6-01 承租人预审
     */
    public TenantPreAuditBody buildTenantPreAuditBody(OrderBase orderBase){
        TenantPreAuditBody body = new TenantPreAuditBody();

        //出租人信息，查询
        Customer customer = customerService.getById(orderBase.getCustomerId());
        //客户姓名
        String customerName = customer.getName();
        //客户身份证号
        String idCarNo = customer.getIdNumber();
        //客户手机号
        String customerPhone = customer.getPhone();
        //详细地址
        String address = orderBase.getInstallationAddress();
        //省份
        String provinceCode = orderBase.getProvinceCode();
        //市
        String cityCode = orderBase.getCityCode();
        //县/区
        String districtCode = orderBase.getAreaCode();


        /**
         * 承租人信息 -- hlsBpMaster
         */
        TenantPreAuditBody.HlsBpMasterDTO hlsBpMasterDTO = new TenantPreAuditBody.HlsBpMasterDTO();
        //商业伙伴类别-承租人-TENANT
        hlsBpMasterDTO.setBpCategory("TENANT");
        //承租人名称 - 客户姓名
        hlsBpMasterDTO.setBpName(customerName);
        //承租人分类-自然人--NP
        hlsBpMasterDTO.setBpClass("NP");
        //证件类型-ID_CARD-身份证
        hlsBpMasterDTO.setIdType("ID_CARD");
        //证件号码
        hlsBpMasterDTO.setIdCardNo(idCarNo);
        //性别-未知 -- UNKNOW
        hlsBpMasterDTO.setGender("UNKNOW");
        //年龄
        hlsBpMasterDTO.setAge(DateUtils.calculateAge(idCarNo));
        //国籍-46-中国
        hlsBpMasterDTO.setNationality("46");
        //手机号
        hlsBpMasterDTO.setCellPhone(customerPhone);
        //业务类型-JOINT_CONSTRUCTION：合作共建
        hlsBpMasterDTO.setServiceType("JOINT_CONSTRUCTION");

        /**
         * 承租人地址信息 -- hlsBpMasterAddress
         */
        TenantPreAuditBody.HlsBpMasterAddressListDTO hlsBpMasterAddress = new TenantPreAuditBody.HlsBpMasterAddressListDTO();
        //地址类型-LEASEITEM_ADDRESS-租赁物（安装）地址
        hlsBpMasterAddress.setAddressType("LEASEITEM_ADDRESS");
        //国家-46-中国
        hlsBpMasterAddress.setCountryCode("46");
        //省
        hlsBpMasterAddress.setProvinceCode(provinceCode);
        //市
        hlsBpMasterAddress.setCityCode(cityCode);
        //区-新增
        hlsBpMasterAddress.setDistrictCode(districtCode);
        //详细地址-order.getInstallationAddress()
        hlsBpMasterAddress.setAddress(address);
        //手机号
        hlsBpMasterAddress.setCellPhone(customerPhone);

        body.setHlsBpMaster(hlsBpMasterDTO);
        //body.setHlsBpMasterAddressList(Collections.singletonList(hlsBpMasterAddress));

        return body;

    }


    /**
     * 6-03 进件信息同步
     */
    public OperatingBody buildOperatingBody(OrderBase orderBase) {
        OperatingBody body = new OperatingBody();

        OperatingBody.PrjProjectLeaseItemListDTO prjProjectLeaseItem = new OperatingBody.PrjProjectLeaseItemListDTO();
        //预审信息查找出租人信息
        //客户信息（出租人信息）
        Customer customer = customerService.getById(orderBase.getCustomerId());
        Reconnoitre reconnoitre = reconnoitreService.getById(orderBase.getOrderId());

        if (NullUtils.isAnyNull(customer, reconnoitre)) {
            throw new BizException("预审信息(客户信息、勘察信息)为空，无法推送进行信息");
        }

        //客户姓名
        String customerName = customer.getName();
        //客户身份号
        String idCarNo = customer.getIdNumber();
        //客户手机号
        String customerPhone = customer.getPhone();
        if (NullUtils.isAnyNull(customerPhone, idCarNo, customerName)) {
            throw new BizException("预审关键信息错误，无法推送进件");
        }


        //省 编码
        String provinceCode = orderBase.getProvinceCode();
        //市 编码
        String cityCode = orderBase.getCityCode();
        //区
        String districtCode = orderBase.getAreaCode();
        //详细地址信息
        String detailAddr = orderBase.getInstallationAddress();
        //账户名
        String bankAccountName = orderBase.getBankAccount();
        //银行卡号
        String bankAccountNum = orderBase.getBankCardNumber();
        //联行号
        String tssBankAccountNum = orderBase.getJointLineNumber();
        //项目公司
        String prjCompanyCode = orderBase.getProjectCompany();

        //单块光伏板组件功率(W)
        String each = reconnoitre.getModulePower().toString();
        //拟安装容量（W）
        Integer installedCapacityReckon = reconnoitre.getInstalledCapacityReckon();
        //预计组件数量(块)
        Integer number = reconnoitre.getModuleNumberReckon();
        //逆变器品牌
        String nbqInerterBrand = reconnoitre.getInverterBrand();
        //产品地区
        String productCode = orderBase.getProductWithArea();


        /**
         * 进件信息
         */
        LeasePrjProject leasePrjProject = leasePrjProjectService.lambdaQuery().last("LIMIT 1").one();
        //预计投放日
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.DATE, Integer.parseInt(leasePrjProject.getLeaseDate()));

        OperatingBody.PrjProjectDTO prjProjectDTO = new OperatingBody.PrjProjectDTO();
        //合作方/厂商
        prjProjectDTO.setManufacturerRegno(leasePrjProject.getManufacturerReno());
        //运维方
        prjProjectDTO.setFactoryRegno(leasePrjProject.getFactoryReno());
        //第一出卖人
        prjProjectDTO.setSellerRegno(leasePrjProject.getSellerReno());
        //合作方进件序号 -- 订单ID
        prjProjectDTO.setPartnersContractNumber(orderBase.getOrderId());
        //商业模式
        prjProjectDTO.setLeaseChannel(leasePrjProject.getLeaseChannel());
        //单据类型
        prjProjectDTO.setDocumentType(leasePrjProject.getDocumentType());
        //业务模式
        prjProjectDTO.setDivision(leasePrjProject.getDivision());
        //预计投放日
        prjProjectDTO.setLeaseDate(DateUtils.parseDateToStr("yyyyMMdd", cal.getTime()));
        //保险购买情况
        prjProjectDTO.setInsuranceFlag(leasePrjProject.getInsuranceFlag());
        //出租人 -- order.项目公司[0]
        prjProjectDTO.setLessorCode(prjCompanyCode);

        /**
         * 租赁物模块 prjProjectLeaseItem
         */
        //租赁物ID -- 订单ID
        prjProjectLeaseItem.setPartnersLeaseItemId(orderBase.getOrderId());
        //租凭物名称 -- 光伏发电设备
        prjProjectLeaseItem.setFullName("光伏发电设备");
        //逆变器品牌
        prjProjectLeaseItem.setInverterBrand(nbqInerterBrand);
        //组件型号 -- 仅传输组件功率数字 -- 单块光伏板组件功率(W)
        prjProjectLeaseItem.setProductModel(each);
        //装机容量 -- 拟安装容量（W）
        prjProjectLeaseItem.setInstalledCapacity(installedCapacityReckon);
        //组件数量 -- 预计组件数量(块)
        prjProjectLeaseItem.setModuleQuantity(number);

        /**
         * 产品信息 - prjProjectProduct
         */
        OperatingBody.PrjProjectProductDTO prjProjectProductDTO = new OperatingBody.PrjProjectProductDTO();
        LeasePrjProjectProduct leasePrjProjectProduct = leasePrjProjectProductService.lambdaQuery().eq(LeasePrjProjectProduct::getCode, productCode).one();
        if (null == leasePrjProjectProduct) {
            throw new BizException("订单 {} 的产品信息 {} 没有找到", orderBase.getOrderId(), productCode);
        }
        //产品方案编号 --  产品编号
        prjProjectProductDTO.setPlanCode(leasePrjProjectProduct.getCode());

        /**
         * 产品参数
         */
        List<OperatingBody.PrjProjectProductDTO.ProductParaListDTO> productParaList = new ArrayList<>();
        //TENANT_INCOME_PRICE - 承租人收益（元/块光伏板/年）
        getProductParaList(leasePrjProjectProduct.getTenantIncomePrice(), productParaList);
        //EQUIPMENT_PRICE - 设备单价（元/瓦)
        getProductParaList(leasePrjProjectProduct.getEquipmentPrice(), productParaList);
        //ELE_PRICE - 电价
        //getProductParaList(leasePrjProjectProduct.getElePrice(), productParaList);
        //BASIC_ELE_TIME - 基准发电小时数
        //getProductParaList(leasePrjProjectProduct.getBasicEleTime(), productParaList);
        //MANUFACTURER_INCONE_RATIO - 厂商收益分成比例
        //getProductParaList(leasePrjProjectProduct.getManufacturerInconeRatio(), productParaList);
        //DECAY_RATE - 光伏板衰减率
        //getProductParaList(leasePrjProjectProduct.getDecayRate(), productParaList);
        //MAINTENANCE_PRICE - 运维费用（元/瓦/年）
        //getProductParaList(leasePrjProjectProduct.getMaintenancePrice(), productParaList);
        //DEPOSIT_RATIO - 保证金比例
        //getProductParaList(leasePrjProjectProduct.getDepositRatio(), productParaList);
        //RESIDUALS_RATE - 残值率
        //getProductParaList(leasePrjProjectProduct.getResidualsRate(), productParaList);
        //DISPOSAL_PRICE-投资资产到期处置价 - 无

        prjProjectProductDTO.setProductParaList(productParaList);

        /**
         * 商业伙伴基本信息
         */
        OperatingBody.BpMasterBaseDtoListDTO.HlsBpMasterDTO hlsBpMasterDTO = new OperatingBody.BpMasterBaseDtoListDTO.HlsBpMasterDTO();
        //承租人名称
        hlsBpMasterDTO.setBpName(customerName);
        //证件号码
        hlsBpMasterDTO.setIdCardNo(idCarNo);
        //手机号
        hlsBpMasterDTO.setCellPhone(customerPhone);

        /**
         * 商业伙伴地址信息
         */
        OperatingBody.BpMasterBaseDtoListDTO.HlsBpMasterAddressListDTO hlsBpMasterAddressListDTO = new OperatingBody.BpMasterBaseDtoListDTO.HlsBpMasterAddressListDTO();
        //地址类型
        hlsBpMasterAddressListDTO.setAddressType("LEASEITEM_ADDRESS");
        //国家 -- 46 -- 中国
        hlsBpMasterAddressListDTO.setCountryCode("46");
        //省
        hlsBpMasterAddressListDTO.setProvinceCode(provinceCode);
        //市
        hlsBpMasterAddressListDTO.setCityCode(cityCode);
        //TODO-3-1 区 - 新增
        hlsBpMasterAddressListDTO.setDistrictCode(districtCode);
        hlsBpMasterAddressListDTO.setAddress(detailAddr);
        if(StringUtils.isAnyEmpty(provinceCode , cityCode , districtCode , customerPhone , detailAddr)){
            throw new BizException("订单{}  同步进件，必要的地址信息不全，无法进件。省码 {} 城市码 {} 区码 {} 安装地址 {} 客户电话 {}"  ,
                    provinceCode , cityCode , districtCode , detailAddr , customerPhone);
        }
        //手机号
        hlsBpMasterAddressListDTO.setCellPhone(customerPhone);

        /**
         * 商业伙伴银行信息
         */
        OperatingBody.BpMasterBaseDtoListDTO.HlsBpMasterBankAccountListDTO hlsBpMasterBankAccountListDTO = new OperatingBody.BpMasterBaseDtoListDTO.HlsBpMasterBankAccountListDTO();
        //账户名称
        hlsBpMasterBankAccountListDTO.setBankAccountName(bankAccountName);
        //银行账号
        hlsBpMasterBankAccountListDTO.setBankAccountNum(bankAccountNum);
        //TSS联行号
        hlsBpMasterBankAccountListDTO.setTssBankNum(tssBankAccountNum);

        OperatingBody.PrjProjectAccountListDTO prjProjectAccount = new OperatingBody.PrjProjectAccountListDTO();
        //02 - 发电户号
        prjProjectAccount.setAccountType("02");
        //账号名称
        prjProjectAccount.setAccountName(bankAccountName);
        //账号
        prjProjectAccount.setAccountNumber(bankAccountNum);
        //TSS联行号
        prjProjectAccount.setTssBankNumber(tssBankAccountNum);


        body.setPrjProject(prjProjectDTO);
        body.setBpMasterBaseDtoList(Collections.singletonList(new OperatingBody.BpMasterBaseDtoListDTO()
                .setHlsBpMaster(hlsBpMasterDTO)
                .setHlsBpMasterAddressList(Collections.singletonList(hlsBpMasterAddressListDTO))
                .setHlsBpMasterBankAccountList(Collections.singletonList(hlsBpMasterBankAccountListDTO))));
        body.setPrjProjectLeaseItemList(Collections.singletonList(prjProjectLeaseItem));
        body.setPrjProjectProduct(prjProjectProductDTO);
        body.setPrjProjectAccountList(Collections.singletonList(prjProjectAccount));
        return body;
    }



    /**
     * 6-04 农户投放审查信息同步
     * 原本使用：
     * 并网阶段推送全部信息
     * 问题点：此时已经完成施工，施工完成到并网，中间有电站检查等环节 约一个月 。 但是此时并网，审查信息存在错误。
     * 解决办法：
     * 施工结束，就推送信息，有错误及时修改。无需等待并网一起推送。节省时间
     */
    public OperatingSignBody buildOperatingSignBody(OrderBase orderBase, boolean isSGFinished){
        OperatingSignBody body = new OperatingSignBody();

        //获取组件信息
        List<Device> zuJianInfo = deviceService.lambdaQuery().eq(Device::getOrderId, orderBase.getOrderId())
                .eq(Device::getDeviceType, Constants.DEVICE_TYPE_ZUJIAN).list();

        //获取逆变器设备信息
        List<Device> nbqInfo = deviceService.lambdaQuery().eq(Device::getOrderId, orderBase.getOrderId())
                .eq(Device::getDeviceType, Constants.DEVICE_TYPE_NBQ).list();
        //Map<String, List<Device>> nbqInfoMap =  nbqInfo.stream().collect(Collectors.groupingBy(Device::getManufacturerShortCode));


        if (NullUtils.isEmpty(zuJianInfo) || NullUtils.isEmpty(nbqInfo)) {
            throw new BizException("订单号{}，农户投放审查信息同步 , 必要的表单信息为空，无法同步", orderBase.getOrderId());
        }

        //组件-组件生产商-code
        String zjProducerFactoryCode = zuJianInfo.get(0).getManufacturerShortCode();
        //组件-规格型号 -- 550 -- 功率
        String zjModel = zuJianInfo.get(0).getModulePower().toString();
        //组件-设备数量
        int zjQuantity = zuJianInfo.size();
        //组件-设备编号
        String zjDeviceSN = zuJianInfo.stream().map(Device::getDeviceNumber).collect(Collectors.joining(","));


        //逆变器-逆变器品牌-code
//        String nbqProducerFactoryCode = "";
//        StringBuilder nbqProducerFactoryStr = new StringBuilder();
//        if (nbqInfoMap.size() > 1) {
//            int size = 0;
//            for (Map.Entry<String, List<Device>> entry : nbqInfoMap.entrySet()) {
//                nbqProducerFactoryStr.append(entry.getKey());
//                if (size != nbqInfoMap.size()) {
//                    nbqProducerFactoryStr.append(",");
//                }
//                size++;
//            }
//            nbqProducerFactoryCode = nbqProducerFactoryStr.toString();
//        } else {
//            nbqProducerFactoryCode = nbqInfo.get(0).getManufacturerShortCode();
//        }
        //逆变器-逆变器品牌-code
        String nbqProducerFactoryCode = nbqInfo.get(0).getManufacturerShortCode();
        if (StringUtils.isBlank(nbqProducerFactoryCode)) {
            nbqProducerFactoryCode = nbqInfo.get(0).getManufacturer();
        }
        //逆变器-规格型号
        String nbqModel = nbqInfo.get(0).getSpecificationsModel();
        //逆变器-设备编号
        String nbqDeviceSN = nbqInfo.stream().map(Device::getDeviceNumber).collect(Collectors.joining(","));

        //电站投保-财产险-实际安装容量(完工容量)
        Design design = btoDesignService.getLatestDesign(orderBase.getOrderId(), true);
        if (null == design) {
            throw new BizException("订单号：{}，设计信息为空！", orderBase.getOrderId());
        }
        Integer sjCapacity = design.getInstalledCapacityDesign();



        /**
         * 进件模块
         */
        OperatingSignBody.PrjProjectDTO prjProjectDTO = new OperatingSignBody.PrjProjectDTO();
        //进件序号 -- 订单ID
        prjProjectDTO.setPartnersContractNumber(orderBase.getOrderId());
        //传输信息类型 -- 10-完工信息
        prjProjectDTO.setInformationType("10");


        /**
         * 租凭物模块
         */
        OperatingSignBody.PrjProjectLeaseItemListDTO prjProjectLeaseItem = new OperatingSignBody.PrjProjectLeaseItemListDTO();
        //租凭物ID -- 订单ID
        prjProjectLeaseItem.setPartnersLeaseItemId(orderBase.getOrderId());
        //组件生产商 -- 组件 -- 简码 -- code
        prjProjectLeaseItem.setModuleProducer(zjProducerFactoryCode);
        //组件型号 -- 组件- 550
        prjProjectLeaseItem.setProductModel(zjModel);
        //逆变器编号 -- 逆变器-设备编号
        prjProjectLeaseItem.setInverterNumber(nbqDeviceSN);
        //装机容量（W）-- 电站投保-财产险-实际安装容量(完工容量)
        prjProjectLeaseItem.setInstalledCapacity(sjCapacity);
        //逆变器品牌 -- 逆变器--拓展字段-code
        prjProjectLeaseItem.setInverterBrand(nbqProducerFactoryCode);
        //逆变器 -- 逆变器-规格型号
        prjProjectLeaseItem.setInverterModel(nbqModel);
        //组件数量 -- 组件-设备数量
        prjProjectLeaseItem.setModuleQuantity(zjQuantity);
        //购售电地址是否一致 - y
        prjProjectLeaseItem.setAddressConsistent("Y");


        /**
         * 组件信息模块
         */
        List<OperatingSignBody.PrjProjectLeaseItemListDTO.ModuleListDTO> list = new ArrayList<>();
        zuJianInfo.forEach(
                sn -> list.add(new OperatingSignBody.PrjProjectLeaseItemListDTO.ModuleListDTO().setModuleCode(sn.getDeviceNumber()))
        );
        prjProjectLeaseItem.setModuleList(list);



        //20-所有信息
        if (!isSGFinished) {
            prjProjectDTO.setInformationType("20");
            //并网信息
            GridConnection bwInfo = gridConnectionService.lambdaQuery()
                    .eq(GridConnection::getOrderId, orderBase.getOrderId()).one();
            if (NullUtils.isNull(bwInfo)) {
                throw new BizException("订单号{}，农户投放审查信息同步 , 并网信息为空，无法同步", orderBase.getOrderId());
            }
            //并网信息-并网合闸时间
            long hwhzDate = bwInfo.getStartTime().getTime();
            //并网日期 -- 并网合闸时间
            prjProjectDTO.setGridTiedDate(DateUtils.parseDateToStr("yyyyMMdd", new Date(hwhzDate)));
            /**
             * 保险信息模块 （传输信息类型字段为：“10-完工信息”时非必传）
             */
            OperatingSignBody.PrjProjectLeaseItemListDTO.InsuranceListDTO insurance = buildOperatingSignUpdateInsurance(orderBase);
            //保险信息模块
            prjProjectLeaseItem.setInsuranceList(Collections.singletonList(insurance));

            /**
             * 账号信息 (传输信息类型字段为：“10-完工信息”时非必传）
             */
            Customer customer = customerService.getById(orderBase.getCustomerId());
            if (NullUtils.isNull(customer)) {
                throw new BizException("该订单{}，客户信息没有找到, 无法农户投放", orderBase.getOrderId());
            }
            OperatingSignBody.PrjProjectAccountListDTO prjProjectAccount = new OperatingSignBody.PrjProjectAccountListDTO();
            //账号类型 -- 02-发电户号
            prjProjectAccount.setAccountType("02");
            //账号名称 -- 客户名称
            prjProjectAccount.setAccountName(customer.getName());
            //账号 -- 银行卡号
            prjProjectAccount.setAccountNumber(orderBase.getBankCardNumber());
            //联行号
            prjProjectAccount.setTssBankNumber(orderBase.getJointLineNumber());
            //账号信息
            body.setPrjProjectAccountList(Collections.singletonList(prjProjectAccount));
        }

        body.setPrjProject(prjProjectDTO);
        body.setPrjProjectLeaseItemList(Collections.singletonList(prjProjectLeaseItem));

        return body;
    }


    /**
     * 6-04-01 并网及商务信息更新
     */
    public OperatingSignBody buildOperatingSignUpdateBody(OrderBase orderBase){
        OperatingSignBody body = new OperatingSignBody();

        //并网信息
        GridConnection bwInfo = gridConnectionService.lambdaQuery()
                .eq(GridConnection::getOrderId, orderBase.getOrderId()).one();

        if (NullUtils.isNull(bwInfo)) {
            throw new BizException("订单 {} 并网及商务信息更新 , 必要的表单信息为空，无法同步" , orderBase.getOrderId());
        }

        //并网信息-并网合闸时间
        long hwhzDate = bwInfo.getStartTime().getTime();
        //并网信息-购售电地址是否一致：(0：（否）不一致，1：（是）一致)
        Byte isConsistent = bwInfo.getIsConsistent();
        if(NullUtils.isNull(isConsistent)){
            isConsistent = 1;
        }
        String addressConsistent = isConsistent == 1 ? "Y" : "N";
        //购售点地址（省）
        String electricProvinceCode = bwInfo.getProvinceCode();
        //购售点地址（市）
        String electricCityCode = bwInfo.getCityCode();
        //购售点地址（区）
        String electricAreaCode = bwInfo.getAreaCode();
        //并网信息-购售点地址（详细地址）
        String electricAddress = bwInfo.getDetailedAddress();
        //并网信息-发电户号
        String fdhh = bwInfo.getGeneratorNumber();

        /**
         * 进件模块
         */
        OperatingSignBody.PrjProjectDTO prjProjectDTO = new OperatingSignBody.PrjProjectDTO();
        //进件序号 -- 订单ID
        prjProjectDTO.setPartnersContractNumber(orderBase.getOrderId());
        //并网日期 -- 并网合闸时间
        prjProjectDTO.setGridTiedDate(DateUtils.parseDateToStr("yyyyMMdd", new Date(hwhzDate)));

        /**
         * 租凭物模块
         */
        OperatingSignBody.PrjProjectLeaseItemListDTO prjProjectLeaseItem = new OperatingSignBody.PrjProjectLeaseItemListDTO();
        //租凭物ID -- 订单ID
        prjProjectLeaseItem.setPartnersLeaseItemId(orderBase.getOrderId());
        //购售电地址是否一致
        if ("N".equals(addressConsistent)) {
            //购售电地址是否一致 - N
            prjProjectLeaseItem.setAddressConsistent(addressConsistent);
            //购售电地址（省）
            prjProjectLeaseItem.setElectricProvinceCode(electricProvinceCode);
            //购售电地址（市）
            prjProjectLeaseItem.setElectricCityCode(electricCityCode);
            //购售电地址（区）
            prjProjectLeaseItem.setElectricAreaCode(electricAreaCode);
            //购售点地址（详细地址）
            prjProjectLeaseItem.setElectricAddress(electricAddress);

        } else {
            //购售电地址是否一致 - y
            prjProjectLeaseItem.setAddressConsistent(addressConsistent);
        }


        /**
         * 保险信息模块
         */
        OperatingSignBody.PrjProjectLeaseItemListDTO.InsuranceListDTO insurance = buildOperatingSignUpdateInsurance(orderBase);
        //保险信息模块
        prjProjectLeaseItem.setInsuranceList(Collections.singletonList(insurance));

        /**
         * 账号信息
         */
        Customer customer = customerService.getById(orderBase.getCustomerId());
        if (NullUtils.isNull(customer)) {
            throw new BizException("该订单{}，客户信息没有找到, 无法农户投放", orderBase.getOrderId());
        }
        OperatingSignBody.PrjProjectAccountListDTO prjProjectAccount = new OperatingSignBody.PrjProjectAccountListDTO();
        //账号类型 -- 02-发电户号
        prjProjectAccount.setAccountType("02");
        //账号名称 -- 客户名称
        prjProjectAccount.setAccountName(customer.getName());
        //账号 -- 并网信息-银行卡号
        prjProjectAccount.setAccountNumber(orderBase.getBankCardNumber());

        //进件信息
        body.setPrjProject(prjProjectDTO);
        //租凭信息
        body.setPrjProjectLeaseItemList(Collections.singletonList(prjProjectLeaseItem));
        //账号信息
        body.setPrjProjectAccountList(Collections.singletonList(prjProjectAccount));

        return body;
    }

    /**
     * 保险信息模块
     */
    private OperatingSignBody.PrjProjectLeaseItemListDTO.InsuranceListDTO buildOperatingSignUpdateInsurance(OrderBase orderBase) {
        //电站投保信息-邮件-财产险
        Insurance dztbInfo = getInsuranceByOrderId(orderBase.getOrderId());

        if (NullUtils.isNull(dztbInfo)) {
            throw new BizException("订单 {} 并网及商务信息更新 , 电站投保信息为空，无法同步" , orderBase.getOrderId());
        }

        //电站投保-财产险-保险日期从
        long ccxDateFrom = dztbInfo.getStartDate().getTime();
        String ccxDateFromStr = DateUtils.parseDateToStr("yyyyMMdd", new Date(ccxDateFrom));
        //电站投保-财产险-保险日期到
        long ccxDateTo = dztbInfo.getEndDate().getTime();
        String ccxDateToStr = DateUtils.parseDateToStr("yyyyMMdd" , new Date(ccxDateTo));
        //电站投保-财产险-保险公司
        String bxCompany = dztbInfo.getInsuranceCompany();
        //电站投保-财产险-保险编号
        String bxNo = dztbInfo.getInsuranceNumber();
        //电站投保-财产险-投保金额
        String tbje = dztbInfo.getInsuredAmount();
        //电站投保-财产险-第一受益人
        String dysyr = dztbInfo.getBeneficiary();

        /**
         * 保险信息模块
         */
        OperatingSignBody.PrjProjectLeaseItemListDTO.InsuranceListDTO insurance = new OperatingSignBody.PrjProjectLeaseItemListDTO.InsuranceListDTO();
        //保险类型 -- 1-财产险
        insurance.setInsuranceType("1");
        ///保险日期从 -- 电站投保-财产险-保险日期从
        insurance.setInsuranceDateFrom(ccxDateFromStr);
        //保险日期到 -- 电电站投保-财产险-保险日期到
        insurance.setInsuranceDateTo(ccxDateToStr);
        //保险公司 -- 电电站投保-财产险-保险公司
        insurance.setInsuranceCompany(bxCompany);
        //保险单号 -- 电电站投保-财产险-保险编号
        insurance.setInsuranceNumber(bxNo);
        //保险金额 -- 电电站投保-财产险-保险金额
        insurance.setInsuranceAmount(Double.valueOf(tbje));
        //第一受益人 -- 电站投保-财产险-第一受益人
        insurance.setFirstBeneficiary(dysyr);

        return insurance;

    }

    /**
     * 构建购售电合同推送接口body
     */
    public PowerSellOlFIleBody buildPowerSellOlFileBody(OrderBase orderBase){
        PowerSellOlFIleBody body = new PowerSellOlFIleBody();
        /**
         * 1 进件模块
         */
        //进件序号 -- 订单ID
        body.setPrjProject(new PowerSellOlFIleBody.PrjProject().setPartnersContractNumber(orderBase.getOrderId()));

        /**
         * 2 租赁物模块
         */
        PowerSellOlFIleBody.PrjProjectLeaseItem prjProjectLeaseItem = new PowerSellOlFIleBody.PrjProjectLeaseItem();
        //租凭物ID -- 订单ID
        prjProjectLeaseItem.setPartnersLeaseItemId(orderBase.getOrderId());

        //查询组件信息  产品型号 逆变器编号
        List<Device> zuJianInfo = deviceService.lambdaQuery().eq(Device::getOrderId, orderBase.getOrderId())
                .eq(Device::getDeviceType, Constants.DEVICE_TYPE_ZUJIAN).list();

        //组件型号 -- 规格型号
        String productModel = zuJianInfo.get(0).getModulePower().toString();
        prjProjectLeaseItem.setProductModel(productModel);

        // 1）不允许有空白符 \s  ,特殊符号[-@#￥%&~^]
        // 2）如果存在多个请用”，“隔开，例如逆变器编号1，逆变器编号2，
        List<Device> nbqInfo = deviceService.lambdaQuery().eq(Device::getOrderId, orderBase.getOrderId())
                .eq(Device::getDeviceType, Constants.DEVICE_TYPE_NBQ).list();
        prjProjectLeaseItem.setInverterNumber(nbqInfo.stream().map(Device::getDeviceNumber).collect(Collectors.joining(",")));

        //购售电合同信息
        GridConnection gridConnection = gridConnectionService.lambdaQuery()
                .eq(GridConnection::getOrderId, orderBase.getOrderId()).one();

        //购购售电地址是否一致
        Byte choose = gridConnection.getIsConsistent();
        String addressConsistent = 1 == choose ? "Y" : "N";
        prjProjectLeaseItem.setAddressConsistent(addressConsistent);

        if ("N".equals(addressConsistent)) {
            //购售电地址(省）
            prjProjectLeaseItem.setElectricProvinceCode(gridConnection.getProvinceCode());
            //购售电地址(市）
            prjProjectLeaseItem.setElectricCityCode(gridConnection.getCityCode());
            //购售电地址(区）
            prjProjectLeaseItem.setElectricAreaCode(gridConnection.getAreaCode());
            //购售电地址(详细地址）
            prjProjectLeaseItem.setElectricAddress(gridConnection.getDetailedAddress());
        }
        body.setPrjProjectLeaseItemList(Collections.singletonList(prjProjectLeaseItem));

        /**
         * 3.1文件明细模块 GDBT_D_01
         */
        List<PowerSellOlFIleBody.FinanceProjectFileInfoDto.FileList> fileLists = new ArrayList<>();
        String psContactFile = gridConnection.getContract();
        if (StringUtils.isNotEmpty(psContactFile)) {
            List<String> uploadFileList = JSONArray.parseArray(psContactFile, String.class);
            if (NullUtils.isNotEmpty(uploadFileList)) {
                for (String uploadFlie : uploadFileList) {
                    PowerSellOlFIleBody.FinanceProjectFileInfoDto.FileList file = new PowerSellOlFIleBody.FinanceProjectFileInfoDto.FileList();
                    String suffix = uploadFlie.substring(uploadFlie.lastIndexOf("."));
                    String fileName = orderBase.getName() + "_" + BizLeaseImage.QUERY_CONTRACT.getFileName() + suffix;
                    file.setFileName(fileName);
                    file.setFileAddress(uploadFlie);
                    file.setFileCode(BizLeaseImage.QUERY_CONTRACT.getFileCode());
                    fileLists.add(file);
                }
            }
        }

        /**
         * 3文件信息
         */
        body.setFinanceProjectFileInfoDto(new PowerSellOlFIleBody.FinanceProjectFileInfoDto()
                .setKeyType("01")
                .setBusinessKey(orderBase.getOrderId())
                .setFileList(fileLists));

        return body;

    }



    /**
     * 保险续保信息推送
     */
    public InsuranceRenewalBody buildInsuranceRenewal(OrderBase orderBase){
        InsuranceRenewalBody body = new InsuranceRenewalBody();
        //TODO 保险续保的业务流程
        Insurance dztbInfo = getInsuranceByOrderId(orderBase.getOrderId());
        if (NullUtils.isNull(dztbInfo)) {
            throw new BizException("保险续保信息推送 , 必要的表单信息为空，无法同步");
        }

        /**
         * 续保模块
         */
        InsuranceRenewalBody.LeaseItemRenewal leaseItemRenewal = new InsuranceRenewalBody.LeaseItemRenewal();
        //业务模式 -- PHOTOVOLTAIC_DEVICES-光伏设备
        leaseItemRenewal.setDivision("PHOTOVOLTAIC_DEVICES");
        //新保险编号 -- 保险编号
        leaseItemRenewal.setInsuranceNumber(dztbInfo.getInsuranceNumber());

        /**
         * 保险信息模块
         */
        InsuranceRenewalBody.Insurance insurance = new InsuranceRenewalBody.Insurance();
        //合作方进件序号 -- 订单ID
        insurance.setPartnersContractNumber(orderBase.getOrderId());
        //租赁物ID/车架号 -- 业务模式为光伏设备则默认为租赁物ID -- 订单ID
        insurance.setBusinessKey(orderBase.getOrderId());
        //保险类型 -- 1 - 财产险
        insurance.setInsuranceType("1");
        //保险日期从
        long ccxDateFrom = dztbInfo.getStartDate().getTime();
        String ccxDateFromStr = DateUtils.parseDateToStr("yyyyMMdd", new Date(ccxDateFrom));
        insurance.setInsuranceDateFrom(ccxDateFromStr);
        //保险日期到
        long ccxDateTo = dztbInfo.getEndDate().getTime();
        String ccxDateToStr = DateUtils.parseDateToStr("yyyyMMdd", new Date(ccxDateTo));
        insurance.setInsuranceDateTo(ccxDateToStr);
        //保险公司
        insurance.setInsuranceCompany(dztbInfo.getInsuranceCompany());
        //投保金额
        insurance.setInsuranceAmount(dztbInfo.getInsuredAmount());
        //第一受益人
        insurance.setFirstBeneficiary(dztbInfo.getBeneficiary());
        body.setInsuranceList(Collections.singletonList(insurance));

        /**
         * 文件明细模块
         */
        List<InsuranceRenewalBody.FinanceProjectFileInfo.FileList> fileLists = new ArrayList<>();
        String fileAddress = dztbInfo.getInsurancePolicyP();
        if (StringUtils.isEmpty(fileAddress)) {
            String suffix = fileAddress.substring(fileAddress.lastIndexOf(".") - 1);
            String fileName = orderBase.getName() + "_" + "续保保险保单（PDF上传）" + suffix;

            InsuranceRenewalBody.FinanceProjectFileInfo.FileList file = new InsuranceRenewalBody.FinanceProjectFileInfo.FileList();
            file.setFileName(fileName);
            file.setFileAddress(fileAddress);
            fileLists.add(file);
        }

        /**
         * 4文件信息
         * */
        body.setFinanceProjectFileInfo(new InsuranceRenewalBody.FinanceProjectFileInfo()
                .setKeyType("01").setFileList(fileLists));


        return body;
    }




    /**
     * 6-05 经营租赁资料与合同推送 - 同步
     */
    public FileContractPushBody buildFileAndContactPushBody(OrderBase orderBase, List<String> types, boolean isLeaseSyncProject){
        FileContractPushBody body = new FileContractPushBody();
        body.setFileList(new ArrayList<>());

        //没有进件
        if (!isLeaseSyncProject) {
            Customer customer = customerService.getById(orderBase.getCustomerId());
            if (null == customer) {
                throw new BizException("订单{}, 没有找到客户信息", orderBase.getOrderId());
            }
            body.setKeyType("02");
            //客户身份号
            body.setBusinessKey(customer.getIdNumber());
            //信息使用授权书 -- 预审
            if (types.contains(Constants.FILE_XXSYSQS_A)) {
                body.getFileList().addAll(getXXSYSQSImagesFileList(orderBase, customer));
            }
        }
        //已经进件
        else {
            body.setKeyType("01");
            //订单ID
            body.setBusinessKey(orderBase.getOrderId());

            //信息使用授权书 -- 风险
            if (types.contains(Constants.FILE_XXSYSQS_B)) {
                body.getFileList().addAll(getXXSYSQSImagesFileList(orderBase));
            }
            //身份证
            if (types.contains(Constants.FILE_SFZ)) {
                body.getFileList().addAll(getSFZImagesFileList(orderBase));
            }
            //银行卡
            if(types.contains(Constants.FILE_YHK)){
                body.getFileList().addAll(getYHKImagesFileList(orderBase));
            }

            //房产证明
            if (types.contains(Constants.FILE_FCZM)) {
                body.getFileList().addAll(getFCZMImagesFileList(orderBase));
            }

            //电站保险保单（PDF文档上传）
            if (types.contains(Constants.FILE_BXD)) {
                body.getFileList().addAll(getBXDImagesFileList(orderBase));
            }
            //房屋外部
            if (types.contains(Constants.FILE_FWWB)) {
                body.getFileList().addAll(getFWWBImagesFileList(orderBase));
            }
            //设计资料
            if (types.contains(Constants.FILE_SJZL)) {
                body.getFileList().addAll(getSJZLImagesFileList(orderBase));
            }
            //房屋内部
            if(types.contains(Constants.FILE_FWNB)){
                body.getFileList().addAll(getFWNBImagesFileList(orderBase));
            }
            //基础安装
            if (types.contains(Constants.FILE_JCAZ)) {
                body.getFileList().addAll(getJCAZImagesFileList(orderBase));
            }
            //支架安装
            if (types.contains(Constants.FILE_ZHIJIA_AZ)) {
                body.getFileList().addAll(getZHIJIAAZImagesFileList(orderBase));
            }
            //组件安装
            if (types.contains(Constants.FILE_ZUJIA_AZ)) {
                body.getFileList().addAll(getZUJIAAZImagesFileList(orderBase));
            }
            //配电、逆变器安装
            if (types.contains(Constants.FILE_PD_NBQ_AZ)) {
                body.getFileList().addAll(getPDNBQAZImagesFileList(orderBase));
            }
            //其他补充
//            if (types.contains(Constants.FILE_PD_QTBC)) {
//                body.getFileList().addAll(getQTBCImagesFileList(orderBase));
//            }
            //并网资料
            if (types.contains(Constants.FILE_BWZL)) {
                body.getFileList().addAll(getBWZLImagesFileList(orderBase));
            }
        }
        return body;
    }


    /**
     * 信息使用授权书  -- 预审(GDBT_A_01)
     */
    private List<FileContractPushBody.FileListDTO> getXXSYSQSImagesFileList(OrderBase orderBase, Customer customer) {
        if (customer == null || StringUtils.isEmpty(customer.getAuthorizationLetter())) {
            throw new BizException("order id {}, image is {}, 没有找到信息使用授权书文件信息", orderBase.getOrderId(), Constants.FILE_XXSYSQS_A);
        }
        return new ArrayList<>(getFiles(orderBase.getName(), customer.getAuthorizationLetter(), BizLeaseImage.QUERY_AUTHORIZATION_LETTER_A));
    }

    /**
     * 信息使用授权书 进件(GDBT_B_04)
     */
    private List<FileContractPushBody.FileListDTO> getXXSYSQSImagesFileList(OrderBase orderBase) {
        Customer customer = customerService.getById(orderBase.getCustomerId());
        if (customer == null || StringUtils.isEmpty(customer.getAuthorizationLetter())) {
            throw new BizException("order id {}, image is {}, 没有找到信息使用授权书文件信息", orderBase.getOrderId(), Constants.FILE_XXSYSQS_B);
        }
        //风险
        return new ArrayList<>(getFiles(orderBase.getName(), customer.getAuthorizationLetter(), BizLeaseImage.QUERY_AUTHORIZATION_LETTER_B));
    }


    /**
     * 身份证  -- 正面(GDBT_B_01) 反面(GDBT_B_02)
     */
    private List<FileContractPushBody.FileListDTO> getSFZImagesFileList(OrderBase orderBase) {
        Customer customer = customerService.getById(orderBase.getCustomerId());
        if (customer == null || StringUtils.isAnyBlank(customer.getIdCardFront(), customer.getIdCardBack())) {
            throw new BizException("order id {}  image is {}，没有找到身份证照片信息", orderBase.getOrderId(), Constants.FILE_SFZ);
        }
        List<FileContractPushBody.FileListDTO> files = new ArrayList<>();
        //身份证正面
        files.addAll(getFiles(orderBase.getName(), customer.getIdCardFront(), BizLeaseImage.QUERY_ID_CARD_FRONT));
        //身份证反面
        files.addAll(getFiles(orderBase.getName(), customer.getIdCardBack(), BizLeaseImage.QUERY_ID_CARD_BACK));
        return files;
    }


    /**
     * 银行卡 -- GDBT_B_05
     */
    public List<FileContractPushBody.FileListDTO> getYHKImagesFileList(OrderBase orderBase) {
        if (StringUtils.isEmpty(orderBase.getBankCardFront())) {
            throw new BizException("order id {}, image is {}, 没有找到银行卡图片信息", orderBase.getOrderId(), Constants.FILE_YHK);
        }
        return new ArrayList<>(getFiles(orderBase.getName(), orderBase.getBankCardFront(), BizLeaseImage.QUERY_BANK_CARD_FRONT));
    }

    /**
     * 房产证明 - GDBT_B_03
     */
    public List<FileContractPushBody.FileListDTO> getFCZMImagesFileList(OrderBase orderBase) {
        Customer customer = customerService.getById(orderBase.getCustomerId());
        if (customer == null) {
            throw new BizException("order id {}  image is {}，没有找到房产证明照片信息", orderBase.getOrderId(), Constants.FILE_FCZM);
        }
        //房屋权属证明
        return new ArrayList<>(getFiles(orderBase.getName(), customer.getPropertyCertificate(), BizLeaseImage.QUERY_PROPERTY_CERTIFICATE));
    }

    /**
     * 基础安装-租赁物照片:  电站基础照+来料检验 -- GDBT_C_06
     */
    private List<FileContractPushBody.FileListDTO> getJCAZImagesFileList(OrderBase orderBase) {
        Construct construct = constructService.lambdaQuery().eq(Construct::getOrderId, orderBase.getOrderId()).one();
        if (construct == null) {
            throw new BizException("order id {}, image is {}, 缺少相关的电站基础照+来料检验图片信息！", orderBase.getOrderId(), Constants.FILE_JCAZ);
        }
        //电站基础照+来料检验
        return new ArrayList<>(getImageVos(orderBase.getName(), construct.getElectricStationMaterial(), BizLeaseImage.QUERY_ELECTRIC_STATION_MATERIAL));
    }

    /**
     * 支架安装-租赁物照片： 支架+防水槽安装 -- GDBT_C_07
     */
    private List<FileContractPushBody.FileListDTO> getZHIJIAAZImagesFileList(OrderBase orderBase) {
        Construct construct = constructService.lambdaQuery().eq(Construct::getOrderId, orderBase.getOrderId()).one();
        if (construct == null) {
            throw new BizException("order id {}, image is {}, 缺少相关的支架+防水槽安装图片信息！", orderBase.getOrderId(), Constants.FILE_ZHIJIA_AZ);
        }
        //支架+防水槽安装
        return new ArrayList<>(getImageVos(orderBase.getName(), construct.getTrestleDistributionBox(), BizLeaseImage.QUERY_TRESTLE_DISTRIBUTION_BOX));
    }

    /**
     * 组件安装-租赁物照片: 组件安装 -- GDBT_C_08
     */
    private List<FileContractPushBody.FileListDTO> getZUJIAAZImagesFileList(OrderBase orderBase) {
        Construct construct = constructService.lambdaQuery().eq(Construct::getOrderId, orderBase.getOrderId()).one();
        if (construct == null) {
            throw new BizException("order id {}, image is {}, 缺少相关的组件安装图片信息！", orderBase.getOrderId(), Constants.FILE_ZUJIA_AZ);
        }
        //组件安装
        return new ArrayList<>(getImageVos(orderBase.getName(), construct.getComponentInstallation(), BizLeaseImage.QUERY_COMPONENT_INSTALLATION));
    }

    /**
     * 配电、逆变器安装-租赁物照片： 逆变器和配电箱 -- GDBT_C_09
     */
    private List<FileContractPushBody.FileListDTO> getPDNBQAZImagesFileList(OrderBase orderBase) {
        Construct construct = constructService.lambdaQuery().eq(Construct::getOrderId, orderBase.getOrderId()).one();
        if (construct == null) {
            throw new BizException("order id {}, image is {}, 缺少相关的逆变器和配电箱、线缆安装、接地系统图片信息！", orderBase.getOrderId(), Constants.FILE_PD_NBQ_AZ);
        }
        List<FileContractPushBody.FileListDTO> files = new ArrayList<>();
        //逆变器和配电箱
        files.addAll(getImageVos(orderBase.getName(), construct.getInverterDistributionBox(), BizLeaseImage.QUERY_INVERTER_DISTRIBUTION_BOX));
        //线缆安装
        files.addAll(getImageVos(orderBase.getName(), construct.getWireRigging(), BizLeaseImage.QUERY_WIRE_RIGGING));
        //接地系统
        files.addAll(getImageVos(orderBase.getName(), construct.getGroundingSystem(), BizLeaseImage.QUERY_GROUNDING_SYSTEM));

        return files;
    }

    /**
     * 其他补充  -- GDBT_C_14
     */
//    public List<FileContractPushBody.FileListDTO> getQTBCImagesFileList(OrderBase orderBase) {
//        Construct construct = constructService.lambdaQuery().eq(Construct::getOrderId, orderBase.getOrderId()).one();
//        if (construct == null) {
//            throw new BizException("order id {}, image is {}, 缺少相关的其他补充图片信息！", orderBase.getOrderId(), Constants.FILE_PD_QTBC);
//        }
//        List<FileContractPushBody.FileListDTO> files = new ArrayList<>();
//
//        return files;
//    }

    /**
     * 并网资料  GDBT_C_01
     */
    private List<FileContractPushBody.FileListDTO> getBWZLImagesFileList(OrderBase orderBase) {
        GridConnection gridConnection = gridConnectionService.lambdaQuery().eq(GridConnection::getOrderId, orderBase.getOrderId()).one();
        Record record = recordService.getById(orderBase.getRecordCertificateId());
        if (gridConnection == null || record == null) {
            throw new BizException("order id {}  image is {}，没有找到并网资料照片信息", orderBase.getOrderId(), Constants.FILE_BWZL);
        }
        List<FileContractPushBody.FileListDTO> files = new ArrayList<>();

        //电站发电量监控截图（发电三天） - 100
        files.addAll(getFiles(orderBase.getName(), gridConnection.getMonitor(), BizLeaseImage.QUERY_MONITOR));
        //备案证 -- 附件
        files.addAll(getFiles(orderBase.getName(), record.getAccessory(), BizLeaseImage.QUERY_RECORD_BINGWANG));
        return files;
    }



    /**
     * 电站保险保单（PDF文档上传） -- GDBT_C_02
     */
    private List<FileContractPushBody.FileListDTO> getBXDImagesFileList(OrderBase orderBase){
        //电站投保-邮件-财产险
        Insurance insurance = getInsuranceByOrderId(orderBase.getOrderId());
        if (insurance == null || StringUtils.isEmpty(insurance.getInsurancePolicyP())) {
            throw new BizException("order id {}, image is {}, 没有找到电站保险保单图片信息", orderBase.getOrderId(), Constants.FILE_BXD);
        }
        return new ArrayList<>(getFiles(orderBase.getName(), insurance.getInsurancePolicyP(), BizLeaseImage.QUERY_INSURANCE_POLICY_P));
    }

    /**
     * 房屋外部 GDBT_C_03
     */
    private List<FileContractPushBody.FileListDTO> getFWWBImagesFileList(OrderBase orderBase) {
        Reconnoitre reconnoitre = reconnoitreService.lambdaQuery().eq(Reconnoitre::getOrderId, orderBase.getOrderId()).one();
        if (reconnoitre == null) {
            throw new BizException("order id {}, imgage is {}, 缺少相关的勘察图片信息！", orderBase.getOrderId(), Constants.FILE_FWWB);
        }
        List<FileContractPushBody.FileListDTO> files = new ArrayList<>();
        //连贯图-屋顶照片（东南角往西北拍）-96
        files.addAll(getFiles(orderBase.getName(), reconnoitre.getRoofSoutheast(), BizLeaseImage.QUERY_ROOF_SOUTHEAST));
        //连贯图-屋顶照片（北往南拍）-96
        files.addAll(getFiles(orderBase.getName(), reconnoitre.getRoofNorth(), BizLeaseImage.QUERY_ROOF_NORTH));
        //连贯图-屋顶照片（西南角往东北拍）-96
        files.addAll(getFiles(orderBase.getName(), reconnoitre.getRoofSouthwest(), BizLeaseImage.QUERY_ROOF_SOUTHWEST));
        //屋顶面整体图-屋顶面整体照（风化和防水）-97
        files.addAll(getFiles(orderBase.getName(), reconnoitre.getRoofWhole(), BizLeaseImage.QUERY_ROOF_WHOLE));
        //楼板厚度照片-98
        files.addAll(getFiles(orderBase.getName(), reconnoitre.getFloorThickness(), BizLeaseImage.QUERY_FLOOR_THICKNESS));
        //房屋外观图-房屋外观全景照-106
        files.addAll(getFiles(orderBase.getName(), reconnoitre.getPanorama(), BizLeaseImage.QUERY_PANORAMA));
        //屋顶无人机航拍图-无人机航拍图（全景俯视）-52
        files.addAll(getFiles(orderBase.getName(), reconnoitre.getAerophotographWhole(), BizLeaseImage.QUERY_AEROPHOTOGRAPH_WHOLE));
        //屋顶无人机航拍图-无人机航拍图（西北角往东南）-52
        files.addAll(getFiles(orderBase.getName(), reconnoitre.getAerophotographNorthwest(), BizLeaseImage.QUERY_AEROPHOTOGRAPH_NORTHWEST));
        //屋顶无人机航拍图-无人机航拍图（东北角往西南）-52
        files.addAll(getFiles(orderBase.getName(), reconnoitre.getAerophotographNortheast(), BizLeaseImage.QUERY_AEROPHOTOGRAPH_NORTHEAST));
        //逆变器安装位置图 - 53
        files.addAll(getFiles(orderBase.getName(), reconnoitre.getInverterPosition(), BizLeaseImage.QUERY_INVERTER_POSITION));
        //配电箱安装位置 -54
        files.addAll(getFiles(orderBase.getName(), reconnoitre.getDistributionBoxPosition(), BizLeaseImage.QUERY_DISTRIBUTION_BOX_POSITION));
        //并网点位置水印相机定位照(选填)
        if (StringUtils.isNotBlank(reconnoitre.getJunctionLocation())) {
            files.addAll(getFiles(orderBase.getName(), reconnoitre.getJunctionLocation(), BizLeaseImage.QUERY_JUNCTION_LOCATION));
        }
        return files;
    }

    /**
     * 房屋内部 GDBT_C_04
     */
    private List<FileContractPushBody.FileListDTO> getFWNBImagesFileList(OrderBase orderBase) {
        Reconnoitre reconnoitre = reconnoitreService.lambdaQuery().eq(Reconnoitre::getOrderId, orderBase.getOrderId()).one();
        if (reconnoitre == null) {
            throw new BizException("order id {}, imgage is {}, 缺少相关的房屋内部片信息！", orderBase.getOrderId(), Constants.FILE_FWNB);
        }
        List<FileContractPushBody.FileListDTO> files = new ArrayList<>();
        //房屋内部结构 - 94
        files.addAll(getFiles(orderBase.getName(), reconnoitre.getInnerStructure(), BizLeaseImage.QUERY_INNER_STRUCTURE));
        //房屋内部环境 - 95
        files.addAll(getFiles(orderBase.getName(), reconnoitre.getInterneMilieu(), BizLeaseImage.QUERY_INTERNE_MILIEU));
        return files;
    }

    /**
     * 设计资料 GDBT_C_05
     */
    private List<FileContractPushBody.FileListDTO> getSJZLImagesFileList(OrderBase orderBase) {
        Reconnoitre reconnoitre = reconnoitreService.lambdaQuery().eq(Reconnoitre::getOrderId, orderBase.getOrderId()).one();
        Design design = btoDesignService.getLatestDesign(orderBase.getOrderId() , true);
        Record record = recordService.getById(orderBase.getRecordCertificateId());
        if (reconnoitre == null || design == null || record == null) {
            throw new BizException("order id {}, imgage is {}, 缺少相关勘察信息，设计信息，备案证信息！", orderBase.getOrderId(), Constants.FILE_SJZL);
        }
        List<FileContractPushBody.FileListDTO> files = new ArrayList<>();
        //安装区域平面草图（勘测记录表）- 正反面 - 99
        files.addAll(getExplorationTableByImage(orderBase.getName(), reconnoitre.getExplorationTable(), BizLeaseImage.QUERY_EXPLORATION_TABLE));
        //其他勘察影像件 - 103
        files.addAll(getOtherImage(orderBase.getName(), reconnoitre.getOtherImages(), BizLeaseImage.QUERY_OTHER_IMAGES));
        //项目定位（今日水印相机定位照） - 104
        //files.addAll(getFiles(orderBase.getName(), reconnoitre.getPosition(), BizLeaseImage.QUERY_POSITION));
        //结构图纸（图片或PDF）-57
        files.addAll(getFiles(orderBase.getName(), design.getStructureChart(), BizLeaseImage.QUERY_STRUCTURE_CHART));
        //电气图（图片或PDF）-58
        files.addAll(getFiles(orderBase.getName(), design.getElectricalDiagram(), BizLeaseImage.QUERY_ELECTRICAL_DIAGRAM));
        //备案证 -- 附件
        files.addAll(getFiles(orderBase.getName(), record.getAccessory(), BizLeaseImage.QUERY_RECORD_SHEJI));
        return files;
    }

    /**
     * 单个图片 -- 处理单个字符串
     */
    private FileContractPushBody.FileListDTO getFile(String orderName, String address, BizLeaseImage bizLeaseImage) {
        if (StringUtils.isAnyBlank(address, orderName)) {
            throw new BizException("{} 的 address:{} 或 orderName:{}为空！", bizLeaseImage.getFileName(), address, orderName);
        }
        FileContractPushBody.FileListDTO file = new FileContractPushBody.FileListDTO();
        String suffix = address.substring(address.lastIndexOf("."));
        file.setFileCode(bizLeaseImage.getFileCode());
        file.setFileName(orderName + "_" + bizLeaseImage.getFileName() + suffix);
        file.setFileAddress(address);
        return file;
    }

    /**
     * 勘察表（正反面） 处理 -- {"back":"","front",""}
     */
    private List<FileContractPushBody.FileListDTO> getExplorationTableByImage(String orderName, String address, BizLeaseImage bizLeaseImage){
        if (StringUtils.isAnyBlank(address, orderName)) {
            throw new BizException("{} 的 address:{} 或 orderName:{}为空！", bizLeaseImage.getFileName(), address, orderName);
        }
        List<FileContractPushBody.FileListDTO> files = new ArrayList<>();
        ImageVo.ExplorationTable explorationTable = JSON.parseObject(address, ImageVo.ExplorationTable.class);
        try {
            files.add(getFile(orderName, explorationTable.getBack(), bizLeaseImage));
            files.add(getFile(orderName, explorationTable.getFront(), bizLeaseImage));
            return files;
        } catch (Exception e) {
            throw new BizException("order id {}  image is {}，该字段无法识别", orderName, bizLeaseImage.getFileName());
        }
    }

    /**
     * 其他勘察影像件 -- 处理 {"imageAddr:["",""]"}
     */
    public List<FileContractPushBody.FileListDTO> getOtherImage(String orderName, String address, BizLeaseImage bizLeaseImage){
        if (StringUtils.isAnyBlank(address, orderName)) {
            throw new BizException("{} 的 address:{} 或 orderName:{}为空！", bizLeaseImage.getFileName(), bizLeaseImage.getFileName());
        }
        List<FileContractPushBody.FileListDTO> files = new ArrayList<>();
        ImageVo.OtherImage otherImage = JSON.parseObject(address, ImageVo.OtherImage.class);
        try {
            List<String> imageStrList = otherImage.getImageAddr();
            for (String imageStr : imageStrList) {
                files.add(getFile(orderName, imageStr, bizLeaseImage));
            }
            return files;
        } catch (Exception e) {
            throw new BizException("order id {}  image is {}，该字段无法识别", orderName, bizLeaseImage.getFileName());
        }
    }


    /**
     * 可以处理单个字符串 也可以处理多个字符串 （其实是转成单个字符串处理）
     */
    private List<FileContractPushBody.FileListDTO> getFiles(String orderName, String addressByJson, BizLeaseImage bizLeaseImage) {
        if (StringUtils.isAnyBlank(addressByJson, orderName)) {
            throw new BizException("{} 的 addressByJson:{} 或 orderName为{}！", bizLeaseImage.getFileName(), addressByJson, orderName);
        }
        List<FileContractPushBody.FileListDTO> files = new ArrayList<>();
        try {
            List<String> addressList = JSONArray.parseArray(addressByJson, String.class);
            addressList.forEach(address -> files.add(getFile(orderName, address, bizLeaseImage)));
        } catch (BizException biz) {
            throw new BizException(biz.getMessage());
        } catch (Exception e) {
            files.add(getFile(orderName, addressByJson, bizLeaseImage));
        }

        return files;
    }

    /**
     * image单个图片 -- 施工影像件
     */
    private FileContractPushBody.FileListDTO getImage(String orderName, String imageName, String imageAddr, BizLeaseImage bizLeaseImage) {
        if (StringUtils.isAnyBlank(imageAddr, imageName, orderName)) {
            throw new BizException("订单名称：{}， {} 的 imageName:{} 或者 imageAddr:{} ",
                    orderName, bizLeaseImage.getFileName(), imageName, imageAddr);
        }
        FileContractPushBody.FileListDTO file = new FileContractPushBody.FileListDTO();
        String suffix = imageAddr.substring(imageAddr.lastIndexOf("."));
        file.setFileCode(bizLeaseImage.getFileCode());
        file.setFileName(orderName + "_" + imageName +"_" + bizLeaseImage.getFileName() + suffix);
        file.setFileAddress(imageAddr);
        return file;
    }


    /**
     * 处理ImageVo的单个字符串  或者 处理ImageVo的ImageList的多个字符串-- 施工影像件
     */
    private List<FileContractPushBody.FileListDTO> getImageVos(String orderName, String fileListStr, BizLeaseImage bizLeaseImage) {
        if (StringUtils.isAnyBlank(fileListStr, orderName)) {
            throw new BizException("图片地址{} 或者 orderName{} 为空！", fileListStr, orderName);
        }
        List<FileContractPushBody.FileListDTO> files = new ArrayList<>();
        List<ImageVo> imageVoList = JSONArray.parseArray(fileListStr, ImageVo.class);
        if (NullUtils.isEmpty(imageVoList)) {
            throw  new BizException("图片列表为空, 资料无法同步推送资方");
        }
        for (ImageVo imageVo : imageVoList) {
            if (NullUtils.isNotEmpty(imageVo.getImageList())) {
                List<ImageVo.Image> imageList =  imageVo.getImageList();
                for (ImageVo.Image image : imageList) {
                    files.add(getImage(orderName, image.getImageName(), image.getImageAddr(), bizLeaseImage));
                }
            }
            if (StringUtils.isNotBlank(imageVo.getImageAddr())) {
                files.add(getImage(orderName, imageVo.getImageName(), imageVo.getImageAddr(), bizLeaseImage));
            }
        }
        return files;
    }

    private Insurance getInsuranceByOrderId(String orderId) {
        //电站投保-财产险  -- 默认
        return insuranceService.lambdaQuery().eq(Insurance::getOrderId, orderId)
                .orderByDesc(Insurance::getCreateTime)
                .last("LIMIT 1")
                .one();
    }

    public String sendHttpsRequestLease(String path, Map<String, Object> params, String leaseBizCode, Object data) throws BizException {
        String apiUrl = leaseUrl + path;
        StringBuilder paramUrl = new StringBuilder();
        if(NullUtils.isNotNull(params)) {
            for (Map.Entry<String, Object> param : params.entrySet()) {
                //key=value 参数名=参数值
                paramUrl.append(param.getKey()).append("=").append(param.getValue()).append("&");
            }
            String paramUrlStr = paramUrl.substring(0, paramUrl.length() - 1);

            //请求token时，有参数
            if (StringUtils.isNotEmpty(paramUrl.toString())) {
                apiUrl = apiUrl + "?" + paramUrlStr;
            }
        }
        //TODO 注释获取token
        //其他场景 url+token
        else {
            apiUrl = apiUrl + "?access_token=" + getLeaseAccessToken().getAccessToken();
        }
        //初始化客户端
        if(NullUtils.isNull(httpRequestMap)){
            init();
        }
        Map.Entry<Map<Integer, Boolean>, HttpRequest> idleHttpRequest = getIdleHttpRequest();


        if (NullUtils.isNotNull(idleHttpRequest)) {
            Map<Integer, Boolean> key = idleHttpRequest.getKey();
            Iterator<Map.Entry<Integer, Boolean>> entryIterator = key.entrySet().iterator();
            Map.Entry<Integer, Boolean> next = entryIterator.next();
            next.setValue(true);

            HttpRequest httpRequest = idleHttpRequest.getValue();
            httpRequest.setUrl(apiUrl);
            JSONObject httpBody = new JSONObject();
            if (NullUtils.isNotNull(data)) {
                JSONArray leasePostBodyBody = new JSONArray();
                leasePostBodyBody.add(data);
                httpBody.put("body", leasePostBodyBody);

                JSONObject leasePostBodyHeader = new JSONObject();
                //TODO 注释获取token
                leasePostBodyHeader.put("serialNumber", getLeaseAccessToken().getJti());
                leasePostBodyHeader.put("systemId", systemId);
                leasePostBodyHeader.put("transactionCode", reqBizCodeFormat(leaseBizCode));
                leasePostBodyHeader.put("transactionTime", DateUtils.dateTimeNow("yyyyMMdd HH:mm:ss"));
                leasePostBodyHeader.put("version", 1);
                httpBody.put("head", leasePostBodyHeader);
                httpRequest.body(JSON.toJSONString(httpBody));
            }
            try {
                log.info("越秀接口请求：---------begin\nurl {} \n body {}", apiUrl, JSON.toJSONString(httpBody));
                LogUtils.leaseLogger.info("========================================== Start ==========================================");
                LogUtils.leaseLogger.info("URL            : {}", httpRequest.getUrl());
                LogUtils.leaseLogger.info("Request Args   : {}", JSON.toJSONString(httpBody , JSONWriter.Feature.PrettyFormat));
                long startTime = System.currentTimeMillis();
                HttpResponse response = httpRequest.execute();
                LogUtils.leaseLogger.info("Time-Consuming : {} ms", System.currentTimeMillis() - startTime);
                log.info("越秀接口请求：---------end\nurl {} \n body {} \n res {}\n res-body {}",
                        apiUrl, JSON.toJSONString(data), JSON.toJSONString(response), JSON.toJSONString(response.body()));

                if (!response.isOk()) {
                    LogUtils.leaseLogger.error("越秀请求失败 response {}",  JSON.toJSONString(response));
                }

                if (apiUrl.contains("oauth/token")) {
                    LogUtils.leaseLogger.info("Response Args  : {}",  JSON.toJSONString(response.body() , JSONWriter.Feature.PrettyFormat));
                    return response.body();
                }
                LeaseHead head = JSON.parseObject(response.body()).getObject("head", LeaseHead.class);
                if (!head.getErrorCode().equals("01")) {
                    log.error("越秀请求业务执行错误 response {}", JSON.toJSONString(response.body()));
                }
                LogUtils.leaseLogger.info("Response Args  : {}",  JSON.toJSONString(response.body() , JSONWriter.Feature.PrettyFormat));

                next.setValue(false);
                return response.body();
            } catch (Exception e) {
                next.setValue(false);
                LogUtils.leaseLogger.error("越秀请求失败url {} \n body {}  exception {}", apiUrl, JSON.toJSONString(data), e.getMessage());
            }

        }
        throw new BizException("越秀请求客户端，未初始化成功");
    }


    /**
     * 初始化证书配置
     */
    @PostConstruct
    private void init() {
        String sslKeyPre = "prod";
        if(!"prod".equals(SpringUtil.getActiveProfile())){
            sslKeyPre = "dev";
        }
        String sslFilePath = sslKeyPre + "_client.p12";
        try {
            KeyStore clientKeyStore = KeyStore.getInstance("PKCS12");
            clientKeyStore.load(new ClassPathResource(sslFilePath).getInputStream(), sslKey.toCharArray());

            KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
            keyManagerFactory.init(clientKeyStore, sslKey.toCharArray());


            TrustManagerFactory tmf = TrustManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
            tmf.init(clientKeyStore);
            //TrustManager[] trustAllCerts =tmf.getTrustManagers();
            TrustManager[] trustAllCerts = new TrustManager[1];
            trustAllCerts[0] = new JavaDemo.miTM();

            SSLContext sslContext = SSLContext.getInstance("TLS");
            sslContext.init(keyManagerFactory.getKeyManagers(), trustAllCerts, new SecureRandom());

            httpRequestMap = new ConcurrentHashMap<>(1000);
            for (int i = 0; i < 1000; i++) {
                HttpRequest request = HttpRequest.post("temp").header(Header.CONTENT_TYPE, "application/json");
                request.setSSLSocketFactory(sslContext.getSocketFactory());
                request.setConnectionTimeout(30 * 1000);  //30 秒超时
                Map<Integer , Boolean> key = new HashMap<>();
                key.put(i, false);
                httpRequestMap.put(key , request);
            }
        } catch (KeyStoreException | CertificateException | IOException | NoSuchAlgorithmException |
                 UnrecoverableKeyException | KeyManagementException e) {
            throw new BizException("越秀https请求证书，初始化失败。。。。");
        }
    }


    /**
    * 获取空闲的请求客户端
    */
    private Map.Entry<Map<Integer, Boolean>, HttpRequest> getIdleHttpRequest() {
        if (NullUtils.isNull(httpRequestMap)) {
            init();
        }
        for (Map.Entry<Map<Integer, Boolean>, HttpRequest> entry : httpRequestMap.entrySet()) {
            Map<Integer, Boolean> key = entry.getKey();
            for (Map.Entry<Integer, Boolean> next : key.entrySet()) {
                if (!next.getValue()) {
                    return entry;
                }
            }
        }
        throw new BizException("没有可用的httpRequest");
    }

    /**
     * 格式化请求头 的业务编码
     * 以固定字符“YX”开头，拼接业务编码+环境。例如：测试环境进件接口为：YX_FINANCE_PROJECT_INFO_SIT。
     * 测试环境：SIT   用户验收环境：UAT   生产环境：PROD
     */
    private String reqBizCodeFormat(String bizCode) {
        String activeFile = SpringUtil.getActiveProfile();
        String suffix = "SIT";
        if ("uat".equals(activeFile) || "dev".equals(activeFile)) {
            suffix = "UAT";
        } else if ("prod".equals(activeFile)) {
            suffix = "PROD";
        }
        return "YX_" + bizCode + "_" + suffix;
    }

    public boolean checkLeaseResponseOk(String bodyString){
        LeaseHead head = JSON.parseObject(bodyString).getObject("head", LeaseHead.class);
        return "01".equals(head.getErrorCode());
    }

    private boolean checkLeaseOperateResponseOk(OperatingRes operatingRes) {
        if ("S".equals(operatingRes.getType()) || "R".equals(operatingRes.getType())) {
            return true;
        }
        return false;
    }

    /**
     * 同步推送资料
     */
    public boolean checkLeaseSyncPushResponseOk(JSONObject jsonObject) {
        if (NullUtils.isNull(jsonObject)) {
            return false;
        }
        String type = jsonObject.get("type").toString();
        if ("S".equals(type)) {
            return true;
        }
        return false;
    }


    /**
     * 越秀主动推送同步订单状态 -- 其实预审通过不会回调该方法
     */
    public LeaseApprovaledNotifyResp syncApprovalLeaseStatus(LeaseApprovalNotifyReq leaseApprovalNotifyReq) {
        if (leaseApprovalNotifyReq == null) {
            return getLeaseApprovalNotifyResp(null, "R", "请求参数为空");
        }
        List<LeaseApprovalNotifyReq.Body> bodyList = leaseApprovalNotifyReq.getBody();
        //如果bodyList为空等于true, 否则false
        //或者 idCardNo和parenerscontractNumber都为空等于true, 否则false
        if (NullUtils.isEmpty(bodyList)
                || (StringUtils.isEmpty(bodyList.get(0).getPrjDocumentStatusDto().getIdCardNo())
                && StringUtils.isEmpty(bodyList.get(0).getPrjDocumentStatusDto().getPartnersContractNumber()))) {
            return getLeaseApprovalNotifyResp(null, "R", "进件序号和证件号码必填其一");
        }
        OrderBase dbOrderBase = null;
        Customer dbCustomer = null;
        //先获取越秀传回来订单号
        String businessKey = bodyList.get(0).getPrjDocumentStatusDto().getPartnersContractNumber();
        //获取不到订单号
        if (StringUtils.isEmpty(businessKey)) {
            //获取客户的身份证号
            businessKey = bodyList.get(0).getPrjDocumentStatusDto().getIdCardNo();
            dbCustomer = customerService.lambdaQuery().eq(Customer::getIdNumber, businessKey).one();
            if (dbCustomer == null) {
                log.error("客户身份证号：{}，客户不存在系统中", businessKey);
                return getLeaseApprovalNotifyResp(businessKey, "R", "客户身份证号不存在合作方系统中，请检查");
            } else {
                //通过客户id查询所属的订单列表
                List<OrderBase> orderBaseList = orderService.lambdaQuery()
                                .eq(OrderBase::getCustomerId, dbCustomer.getCustomerId())
                                .orderByDesc(OrderBase::getCreateTime).list();
                if (orderBaseList.isEmpty()) {
                    //不报错 --- 该方法是回调给越秀，报错会中断返回信息。
                    log.error("该客户：{}，不存在订单", dbCustomer.getCustomerId());
                    return getLeaseApprovalNotifyResp(businessKey, "R", "该客户不存在订单, 请输入正确的身份号码");
                } else {
                    //将订单列表提取成Map，key为订单Id，value为订单对象，为了避免筛选完再查询
                    Map<String, OrderBase> orderBaseMap = orderBaseList.stream().collect(Collectors.toMap(OrderBase::getOrderId, orderBase -> orderBase));
                    List<String> orderIds = orderBaseList.stream().map(OrderBase::getOrderId).collect(Collectors.toList());
                    //筛选出待越秀审核的预审信息的订单列表
                    List<OrderState> orderStateList = btoOrderStateService.getOrderStateList(orderIds,
                            BizStageEnum.PRE_APPROVAL.getStageId(), BizTaskEnum.TASK_YSXX.getTaskId(),
                            BizTaskStateEnum.WAITING_APPROVAL_LEASE.getStateId());
                    if (NullUtils.isEmpty(orderStateList)) {
                        log.error("该客户：{}，不存在待越秀审核的预审信息", dbCustomer.getCustomerId());
                        return getLeaseApprovalNotifyResp(businessKey, "R", "该客户不存在待资方审核的预审信息，如果是其他审核状态，请输入进件序号");
                    } else if (orderStateList.size() > 1){
                        log.warn("该客户：{}，存在多个待越秀审核的预审信息", dbCustomer.getCustomerId());
                    }
                    //存放筛选完的订单信息
                    List<OrderBase> orderBasesNewList = new ArrayList<>();
                    for (OrderState orderState : orderStateList) {
                        orderBasesNewList.add(orderBaseMap.get(orderState.getOrderId()));
                    }
//                    if (orderBaseList.size() > 1) {
//                        log.warn("该客户：{}，存在多个得资方审核的订单", dbCustomer.getCustomerId());
//                        return getLeaseApprovalNotifyResp(businessKey, "R", "该客户不存在待资方审核的，如果是其他审核状态，请输入合作方进件序号");
//                    }
//                    List<OrderBase> orderBasesNewList = new ArrayList<>();
                    orderBaseList.add(dbOrderBase);
                    return getRespByDecideLeaseState(leaseApprovalNotifyReq, businessKey, orderBasesNewList);
                }
            }
        } else {
            dbOrderBase = orderService.getById(businessKey);
            if (dbOrderBase == null) {
                log.error("该订单号：{}，越秀同步状态失败，订单不存在", businessKey);
                return getLeaseApprovalNotifyResp(businessKey, "R", "进件序号不存在合作方系统中，请检查");
            }
            List<OrderBase> orderBaseList = new ArrayList<>();
            orderBaseList.add(dbOrderBase);
            return getRespByDecideLeaseState(leaseApprovalNotifyReq, businessKey, orderBaseList);
        }
    }

    public LeaseApprovaledNotifyResp getRespByDecideLeaseState(LeaseApprovalNotifyReq leaseApprovalNotifyReq, String businessKey, List<OrderBase> orderBaseList) {
        try {
            for (OrderBase orderBase : orderBaseList) {
                decideLeaseState(leaseApprovalNotifyReq, businessKey, orderBase);
            }
        } catch (BizException biz) {
            log.error("系统报错: "+biz.getErrMsg());
            return getLeaseApprovalNotifyResp(businessKey, "R", biz.getMessage());
        }
        catch (Exception e) {
            log.error("系统报错: "+e);
            return getLeaseApprovalNotifyResp(businessKey, "E", "系统报错");
        }

        return getLeaseApprovalNotifyResp(businessKey, "S", "接口同步成功！");
    }

    public void decideLeaseState(LeaseApprovalNotifyReq leaseApprovalNotifyReq, String businessKey, OrderBase dbOrderBase) {
        LeaseApprovalNotifyReq.PrjProjectOperatingLeaseStatus prjProjectOperatingLeaseStatus = leaseApprovalNotifyReq.getPrjProjectOperatingLeaseStatus();
        if (prjProjectOperatingLeaseStatus == null || StringUtils.isEmpty(prjProjectOperatingLeaseStatus.getTenantStatus())) {
            throw new BizException("缺少承租人预审状态");
        }
        LeaseReview leaseReviewByDb = leaseReviewService.lambdaQuery().eq(LeaseReview::getOrderId, dbOrderBase.getOrderId()).one();

        leaseStateHandler.decideLeaseStateToBtoState(dbOrderBase, leaseReviewByDb, leaseApprovalNotifyReq.getPrjProjectOperatingLeaseStatus());

        //记录审核记录
        LeaseReview leaseReview = new LeaseReview();
        BeanUtils.copyProperties(leaseApprovalNotifyReq.getPrjProjectOperatingLeaseStatus(), leaseReview);//状态信息
        leaseReview.setOrderId(dbOrderBase.getOrderId());//订单ID
        leaseReview.setBusinessKey(businessKey);//身份证或者订单ID
        if (null != leaseReviewByDb) {
            leaseReview.setLeaseReviewId(leaseReviewByDb.getLeaseReviewId());//主键ID
        }
        leaseReviewService.saveOrUpdate(leaseReview);
    }


    /**
     * 回调返回体资方的头部  head
     */
    public LeaseApprovaledNotifyResp getLeaseApprovalNotifyResp(String businessKey, String type, String message) {
        LeaseApprovaledNotifyResp resp = new LeaseApprovaledNotifyResp();
        LeaseApprovaledNotifyResp.Body respBody = new LeaseApprovaledNotifyResp.Body();
        LeaseApprovaledNotifyResp.Head respHead = new LeaseApprovaledNotifyResp.Head();
        respBody.setBusinessKey(businessKey);
        respBody.setType(type);
        respBody.setMessage(message);

        //TODO 注释获取token
        //respHead.setSerialNumber(getLeaseAccessToken().getJti());
        respHead.setErrorMessage(null);
        respHead.setSystemId(systemId);
        respHead.setTransactionCode(reqBizCodeFormat("FINANCE_PROJECT_OL_STATUS_SEND"));
        respHead.setTransactionTime(DateUtils.dateTimeNow("yyyyMMdd HH:mm:ss"));
        respHead.setErrorMessage(message);
        if ("E".equals(type) || "R".equals(type)) {
            respHead.setErrorCode("02");
        } else if ("S".equals(type)) {
            respHead.setErrorCode("01");
        }
        respHead.setVersion(1);
        resp.setHead(respHead);
        return resp;
    }

    /**
     * 资方状态 --> 博通状态
     */
    public void decideLeaseStateToBtoState(OrderBase orderBase, LeaseApprovalNotifyReq.PrjProjectOperatingLeaseStatus prjProjectOperatingLeaseStatus) {
        LeaseReview leaseReviewByDb = leaseReviewService.lambdaQuery().eq(LeaseReview::getOrderId, orderBase.getOrderId()).one();
        leaseStateHandler.decideLeaseStateToBtoState(orderBase, leaseReviewByDb, prjProjectOperatingLeaseStatus);
    }

    /**
     * 构造产品方案
     */
    private void getProductParaList (String jsonStr, List<OperatingBody.PrjProjectProductDTO.ProductParaListDTO> productParaList) {
        try {
            JSONArray priceList = JSON.parseArray(jsonStr);
            for (Object object : priceList) {
                OperatingBody.PrjProjectProductDTO.ProductParaListDTO productParaListDTO = JSON.parseObject(object.toString(), OperatingBody.PrjProjectProductDTO.ProductParaListDTO.class);
                if (StringUtils.isAnyBlank(productParaListDTO.getProductParaName(), productParaListDTO.getLeaseTermFrom(), productParaListDTO.getLeaseTermTo())
                        || NullUtils.isNull(productParaListDTO.getProductParaName())) {
                    log.warn("越秀产品数据为空 {} " , JSON.toJSONString(productParaListDTO));
                    continue;
                }
                productParaList.add(productParaListDTO);
            }
        } catch (Exception e) {
            try {
                OperatingBody.PrjProjectProductDTO.ProductParaListDTO productParaListDTO = JSON.parseObject(jsonStr, OperatingBody.PrjProjectProductDTO.ProductParaListDTO.class);
                if (StringUtils.isAnyBlank(productParaListDTO.getProductParaName(), productParaListDTO.getLeaseTermFrom(), productParaListDTO.getLeaseTermTo())
                        || NullUtils.isNull(productParaListDTO.getProductParaName())) {
                    log.warn("越秀产品数据为空 {} " , JSON.toJSONString(productParaListDTO));
                    return;
                }
                productParaList.add(productParaListDTO);
            } catch (Exception el) {
                throw new BizException("PrjProjectProduct的数据不符合json格式 {}"  ,jsonStr );
            }
        }
    }
}
